home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 301_01 / lif.c < prev    next >
C/C++ Source or Header  |  1989-12-28  |  17KB  |  1,061 lines

  1. /*
  2.     HEADER:      CUG301;
  3.     TITLE:       Conway's game of life;
  4.     DATE:        09/30/89;
  5.     DESCRIPTION: "This program is an example of the usage of the pull-down
  6.                       graphics menu system (menu.c/menu.h) on the same disk.";
  7.     KEYWORDS:       mathematical games, finite automata;
  8.     FILENAME:       LIF.C;
  9.     WARNINGS:       "The author claims copyrights and authorizes
  10.                       non-commercial use only.";
  11.     AUTHORS:       John Muczynski;
  12.     COMPILERS:   Turbo C version 2.0;
  13. */
  14.  
  15. /*
  16.     lif.c
  17.  
  18.     Conway's game of life.
  19.  
  20.     (uses menu)
  21.  
  22.     (c) Copyright 1989 by John Muczynski. All Rights Reserved.
  23. */
  24.  
  25.  
  26. /*      BULLETINS
  27.  
  28. jsm    09/04/89    known problems:
  29.     1. the box is not being turned off properly.
  30.     2. add a menu so that 1. is a feature after the bug is fixed.
  31.     3. make global commands work inside of box (run/seed/...)
  32.     4. the main computation loop can be made to run faster by using
  33.        a state table.
  34.     5. if you stamp when no file is active, then it blows up.
  35.     6. if you stamp when part of the box isn't on the plane, then
  36.         it blows up.  (should wrap-around)
  37.  
  38. FUTURE EXPANSION:
  39. jsm      09/29/89 -Need to check details before executing each function
  40.                    from the user's keys.  For example, the [?][b][r] function
  41.                    will run into never-never land if you execute it before
  42.                    specifing a block.
  43.                   -Need to assign default hot-keys.
  44.                   -Need functions to mirror image the box over either the 
  45.                    x or the y axis.  A second cursor (and box) would also
  46.                    be useful.
  47.                   -Need to take the input for the file name from the MENU
  48.                    buffer so that macros can name files to be loaded and
  49.                    saved.
  50.                   -Need to optimize the run-time loop with a state machine
  51.                    so that it runs faster.
  52.  
  53. */
  54.  
  55.  
  56. #include <stdlib.h>
  57. #include <stdio.h>
  58. #include <time.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61.  
  62. #include <bios.h>
  63. #include <graphics.h>
  64.  
  65.  
  66.  
  67. #include "menu.h"
  68.  
  69.  
  70. #define SIZE   5
  71. #define COLS  17    /* MAX OF 17 MIN OF  ??1?? */
  72. #define ROWS  60    /* MAX OF 60 MIN OF        */
  73.  
  74. /* HOW MUCH SPACE TO LEAVE AT LEFT OF SCREEN */
  75. #define COLOFF 11
  76.  
  77. /* HOW MUCH SPACE TO LEAVE AT TOP OF SCREEN (FOR MENUS) */
  78. #define ROWOFF 30    /* MIN OF 30 OR SO */
  79.  
  80.  
  81. void initgr();
  82. void onblk();
  83.  
  84. typedef int plane[COLS][ROWS];
  85.  
  86.   plane data1 = {0};
  87.   plane data2 = {0};
  88.  
  89.   plane *old_ptr = &data1;
  90.   plane *new_ptr = &data2;
  91.   plane *temp_ptr = 0;
  92.  
  93. #define OLD_DATA (*old_ptr)
  94. #define NEW_DATA (*new_ptr)
  95.  
  96. void cleardat();
  97.  
  98. static int oldX=0, oldY=0;
  99. static int curX=0, curY=0;
  100. static int blockX=0, blockY=0, blockon=0;
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108. FILE *infil;
  109. FILE *outfil;
  110.  
  111.  
  112. int writeit(int val)
  113. {
  114.   fprintf(outfil,"%c",val*( '*' - '.' ) +'.');
  115.   return(val);
  116. };
  117. void writelf()
  118. {
  119.   fprintf(outfil,"\n");
  120. };
  121.  
  122.  
  123.  
  124. static failflag=0;
  125.  
  126. /* doesn't use param that is passed */
  127. int readit()
  128. {
  129.   unsigned char ch;
  130.   int val;
  131.  
  132.   fscanf(infil,"%c",&ch);
  133.   val = (ch!='.');        /* IF ERROR, THEN MAKE IT 'ON' */
  134.   return(val||failflag);
  135. };
  136.  
  137. void readlf()
  138. {
  139.   char ch;
  140.  
  141.   fscanf(infil,"%c",&ch);
  142.   if (ch!='\n') failflag=1;
  143. };
  144.  
  145.  
  146.   static int temp;
  147. #define swapint(a,b) {temp=a; a=b; b=temp;}
  148.  
  149.  
  150.  
  151.  
  152. /* do something to the marked block */
  153. void eachblk(funct,functlf)
  154.   int funct(int val);
  155.   void functlf();
  156. {
  157.   int x,y;
  158.   int ex, ey;
  159.   int i,j, mask, oldval,newval;
  160.   int fx,fy;
  161.   int bX,bY;
  162.   failflag=0;
  163.  
  164.   if (blockon==1) {
  165.     bX=blockX;
  166.     bY=blockY;
  167.   };
  168.   if (blockon==2) {
  169.     bX=oldX-blockX;
  170.     bY=oldY-blockY;
  171.   };
  172.  
  173.  
  174.     fx=bX;
  175.     fy=bY;
  176.  
  177.     ex=oldX;
  178.     ey=oldY;
  179.  
  180.     if (ex<fx) swapint(ex,fx);
  181.     if (ey<fy) swapint(ey,fy);
  182.  
  183.     for(j=fy;j<=ey;j++){
  184.       for(i=fx;i<=ex;i++){
  185.     x=i/8;
  186.     mask = (1 << (i%8));
  187.     y=j;
  188.  
  189.     oldval = ( (NEW_DATA[x][y] & mask) != 0);
  190.     newval = (funct(oldval) != 0);
  191.     if (newval!=oldval) {
  192.       NEW_DATA[x][y] = NEW_DATA[x][y] ^ mask;
  193.       if( (OLD_DATA[x][y] & mask) == (NEW_DATA[x][y] & mask) ) {
  194.         OLD_DATA[x][y] = OLD_DATA[x][y] ^ mask;
  195.       };
  196.     };
  197.  
  198.       }; /* end for i */
  199.       functlf();
  200.     }; /* end for j */
  201. };
  202.  
  203.  
  204.  
  205.  
  206.  static char filnam[80];
  207.  static char *root = "";  /* WAS   "IMAGES\\"   */
  208.  
  209. /* turn off graphics and get a file name */
  210. void getname(char *filnam)
  211. {
  212.   int len;
  213.   char base[40];
  214.  
  215.   savescr();
  216.  
  217.   system("dir /w images");
  218.   printf("\n\n\nEnter the base file name: ");
  219.   fgets(base,40,stdin);
  220.  
  221.   len = strlen(base);
  222.   if (isspace(base[len-1]) ) len--;
  223.   base[len]='\0';
  224.  
  225.   strcpy(filnam,root);
  226.   strcat(filnam,base);
  227.   printf("\n using '%s'\n\n",filnam);
  228. };
  229.  
  230.  
  231. void readblk()
  232. {
  233.   int i,j;
  234.   char ch;
  235.  
  236.  
  237.   getname(filnam);
  238.   infil = fopen(filnam,"r");
  239.   fscanf(infil,"%d %d%c",&i,&j,&ch);
  240.  
  241.  
  242.   fclose(infil);
  243.   restorescr();
  244.  
  245.     blockon=2;
  246.     blockX=1-i;
  247.     blockY=1-j;
  248.   onblk();
  249. };
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257. /* doesn't use param that is passed */
  258. int fillit()
  259. {
  260.   return(1);
  261. };
  262. void filllf()
  263. {
  264. };
  265.  
  266. void fillblk()
  267. {
  268.   eachblk(fillit,filllf);
  269. };
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276. /* doesn't use param that is passed */
  277. int emptyit()
  278. {
  279.   return(0);
  280. };
  281. void emptylf()
  282. {
  283. };
  284.  
  285. void emptyblk()
  286. {
  287.   eachblk(emptyit,emptylf);
  288. };
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295. int revit(int it)
  296. {
  297.   return(!it);
  298. };
  299. void revlf()
  300. {
  301. };
  302.  
  303. void reverseblk()
  304. {
  305.   eachblk(revit,revlf);
  306. };
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314. void enterblk()
  315. {
  316.   int i,j;
  317.   char ch;
  318.  
  319.   infil = fopen(filnam,"r");
  320.   fscanf(infil,"%d %d%c",&i,&j,&ch);
  321.  
  322.     blockon=2;
  323.     blockX=1-i;
  324.     blockY=1-j;
  325.  
  326.  
  327.   eachblk(readit,readlf);
  328.   fclose(infil);
  329.  
  330. };
  331.  
  332.  
  333.  
  334. void writeblk()
  335. {
  336.   char filnam[80];
  337.   int x,y;
  338.   int ex, ey;
  339.   int i,j;
  340.   int bX,bY;
  341.  
  342.   if (blockon==1) {
  343.     bX=blockX;
  344.     bY=blockY;
  345.   };
  346.   if (blockon==2) {
  347.     bX=oldX-blockX;
  348.     bY=oldY-blockY;
  349.   };
  350.  
  351.  
  352.  
  353.     x=bX;
  354.     y=bY;
  355.  
  356.     ex=oldX;
  357.     ey=oldY;
  358.  
  359.     if (ex<x) swapint(ex,x);
  360.     if (ey<y) swapint(ey,y);
  361.  
  362.     i=ex-x+1;
  363.     j=ey-y+1;
  364.  
  365.  
  366.  
  367.   getname(filnam);
  368.   outfil = fopen(filnam,"w");
  369.   fprintf(outfil,"%d %d\n",i,j);
  370.  
  371.   eachblk(writeit,writelf);
  372.   fclose(outfil);
  373.  
  374.   restorescr();
  375. };
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386. /* turn the block on or off */
  387. void putblk(col)
  388.  int col;
  389. {
  390.   int x,y;
  391.   int ex, ey;
  392.   int bX,bY;
  393.  
  394.  
  395.   if (blockon==1) {
  396.     bX=blockX;
  397.     bY=blockY;
  398.   };
  399.   if (blockon==2) {
  400.     bX=oldX-blockX;
  401.     bY=oldY-blockY;
  402.   };
  403.  
  404.   if (blockon) {
  405.     x=bX*SIZE+SIZE+1+COLOFF-2;
  406.     y=bY*SIZE+SIZE+1+ROWOFF    -2;
  407.  
  408.     ex=oldX*SIZE+SIZE+1+COLOFF -2;
  409.     ey=oldY*SIZE+SIZE+1+ROWOFF        -2;
  410.  
  411.     if (ex<x) swapint(ex,x);
  412.     if (ey<y) swapint(ey,y);
  413.  
  414.     setcolor(col);
  415.     rectangle(x,y,ex+SIZE,ey+SIZE);
  416.   };
  417. };
  418.  
  419. void onblk()
  420. {
  421.   putblk(15);
  422. };
  423.  
  424. void offblk()
  425. {
  426.   putblk(00);
  427. };
  428.  
  429.  
  430.  
  431. void rim()
  432. {
  433.   int x1,y1;
  434.   int x2,y2;
  435.  
  436.   x1=8*COLS *SIZE+SIZE+1+COLOFF-2;
  437.   y1=ROWS   *SIZE+SIZE+1+ROWOFF     -2;
  438.  
  439.   x2=          SIZE+1+COLOFF-2;
  440.   y2=          SIZE+1+ROWOFF     -2;
  441.  
  442.   setcolor(15);
  443.   rectangle(x1+1,y1+1,x2-1,y2-1);
  444. };
  445.  
  446.  
  447.  
  448. void cleardat()
  449. {
  450.   int i,j;
  451.  
  452.  
  453.   offblk();
  454.   blockon=0;
  455.  
  456.   clearviewport();
  457.   rim();
  458.  
  459.   for(i=0;i<COLS;i=i+2){
  460.     for(j=0;j<ROWS;j=j+3){
  461.       OLD_DATA[i][j] = 0;
  462.       NEW_DATA[i][j] = 0;
  463.     };
  464.   };
  465. };
  466.  
  467.  
  468.  
  469. void randdata()
  470. {
  471.   int i,j;
  472.   for(i=0;i<COLS;i=i+1){        
  473.     for(j=0;j<ROWS;j=j+1){
  474.       OLD_DATA[i][j] = (rand() % 256)& 0xFF;
  475.       NEW_DATA[i][j] = OLD_DATA[i][j] ^ 0xFF;
  476.     };
  477.   };
  478. };
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486. void neighbor(funct)
  487.   int funct(int);
  488. {
  489.   int row_before, row_here, row_after;
  490.   int col_here, shiftsize;
  491.   int bits_before, bits_here, bits_after;
  492.   int col_mod, bitpos;
  493.   int mask;
  494.   int newmod;    /* value of current row,col */
  495.  
  496.   row_before = ROWS-1;
  497.   row_here = 0;
  498.   row_after = 1;
  499.  
  500. nextrow:
  501.   /* load up first 9 bits to be the last 1 and the leftmost 8 */
  502.   bits_before = ( (OLD_DATA[0][row_before]) <<1) | ( 1&( (OLD_DATA[COLS-1][row_before])>>7 ) );
  503.   bits_here   = ( (OLD_DATA[0][row_here]) <<1)   | ( 1&( (OLD_DATA[COLS-1][row_here])>>7     ) );
  504.   bits_after  = ( (OLD_DATA[0][row_after]) <<1)  | ( 1&( (OLD_DATA[C